import json
from loguru import logger
import operator
from functools import reduce

from django.utils import six
from django.contrib.auth.models import AnonymousUser
from mongoengine.queryset import visitor
from rest_framework.filters import BaseFilterBackend, SearchFilter, OrderingFilter


def get_as_kwargs(request):
    params = request.GET.dict()
    if "as" not in params:
        return {}
    as_params = json.loads(params.get("as", "{}"))
    return as_params


class MongoSearchFilter(SearchFilter):
    """
    适配Mongo模型视图的Search过滤器
    """

    def filter_queryset(self, request, queryset, view):
        search_fields = getattr(view, "search_fields", None)
        search_terms = self.get_search_terms(request)
        if not search_fields or not search_terms:
            return queryset
        orm_lookups = [self.construct_search(six.text_type(search_field)) for search_field in search_fields]
        if not orm_lookups:
            return queryset
        conditions = []
        for search_term in search_terms:
            queries = [visitor.Q(**{orm_lookup: search_term}) for orm_lookup in orm_lookups]
            conditions.append(reduce(operator.or_, queries))
        queryset = queryset.filter(reduce(operator.and_, conditions))
        return queryset


class MongoOrderingFilter(OrderingFilter):
    """
    适配Mongo模型视图的Search过滤器
    """

    def get_valid_fields(self, queryset, view, context={}):
        valid_fields = getattr(view, "ordering_fields", self.ordering_fields)
        if valid_fields is None:
            return self.get_default_valid_fields(queryset, view, context)
        elif valid_fields == "__all__":
            # View explicitly allows filtering on any model field
            model = view.get_serializer().__class__.Meta.model
            valid_fields = [
                (field_name, getattr(field, "verbose_name", field_name)) for field_name, field in model._fields.items()
            ]
        else:
            valid_fields = [(item, item) if isinstance(item, six.string_types) else item for item in valid_fields]

        return valid_fields


class AdvancedSearchFilter(BaseFilterBackend):
    """
    高级搜索过滤器
    """

    def filter_queryset(self, request, queryset, view):
        as_kwargs = get_as_kwargs(request)
        if as_kwargs:
            queryset = queryset.filter(**as_kwargs)
        return queryset


class MongoAdvancedSearchFilter(BaseFilterBackend):
    """
    mongo高级搜索过滤器
    """

    def filter_queryset(self, request, queryset, view):
        as_kwargs = get_as_kwargs(request)
        if as_kwargs:
            queryset = queryset.filter(**as_kwargs)
        return queryset


class DataLevelPermissionsFilter(BaseFilterBackend):
    """
    数据 级权限过滤器
    0. 获取用户的部门id，没有部门则返回空
    1. 判断过滤的数据是否有创建人所在部门 "creator" 字段,没有则返回全部
    2. 如果用户没有关联角色则返回本部门数据
    3. 根据角色的最大权限进行数据过滤(会有多个角色，进行去重取最大权限)
    3.1 判断用户是否为超级管理员角色/如果有1(所有数据) 则返回所有数据

    4. 只为仅本人数据权限时只返回过滤本人数据，并且部门为自己本部门(考虑到用户会变部门，只能看当前用户所在的部门数据)
    5. 自定数据权限 获取部门，根据部门过滤

    **现行**
    """

    def filter_queryset(self, request, queryset, view):
        if isinstance(request.user, AnonymousUser):
            return queryset.none()

        # 0. 获取用户的部门id，没有部门则返回空
        user_dept_id = getattr(request.user, "dept_id")
        if getattr(request.user, "user_type", None) != 2:
            if not user_dept_id:
                return queryset.none()

            # 1. 判断过滤的数据是否有创建人所在部门 "dept_belong_id" 字段
            # if not getattr(queryset.model, "dept_belong_id", None):
            #     return queryset

            # 2. 如果用户没有关联角色则返回本部门数据
            if not hasattr(request.user, "role"):
                return queryset.filter(dept_belong_id=user_dept_id)

            user_empid = getattr(request.user, "username")
            if not user_empid:
                return queryset.none()

        # 3. 根据所有角色 获取所有权限范围
        role_list = request.user.role.filter(status="1").values("admin", "dataScope", "domainFields", "modelKey")
        dataScope_list = []
        domain_fields = {}
        dept_data = {}
        dept_perm = False
        salary_perm = False

        for ele in role_list:
            # 3.1 判断用户是否为超级管理员角色/如果有1(所有数据) 则返回所有数据
            if "1" == ele.get("dataScope") or ele.get("admin") == True:
                return queryset
            if ele.get("dataScope") == "3" and ele.get("domainFields") and ele.get("modelKey"):
                model = ele["modelKey"]
                domain = ele["domainFields"].split(",")
                dept_data[model] = dept_data.get(model, []) + domain
                dept_perm = True
            dataScope_list.append(ele.get("dataScope"))
            if ele.get("domainFields") and ele.get("modelKey") and ele.get("dataScope") == "5":
                if ele.get("modelKey") != "BaseModel":
                    if ele.get("modelKey") in domain_fields:
                        domain_fields[ele.get("modelKey")] += ele.get("domainFields").split(",")
                    else:
                        domain_fields[ele.get("modelKey")] = ele.get("domainFields").split(",")
                elif ele.get("domainFields") == "emp_id":
                    salary_perm = True

        if dept_perm and user_dept_id and "UserProfile" == queryset.model._meta.object_name:
            return queryset.filter(dept=user_dept_id)

        if salary_perm and issubclass(queryset.model, BaseModel):
            return queryset.filter(emp_id=user_empid)

        if dept_data and user_empid:
            dept = list(Em_Basic.objects.filter(emp_id=user_empid).values_list("dept", flat=True))
            dept_user = list(Em_Basic.objects.filter(dept__in=dept).values_list("id", flat=True))
            params = {}
            for k, v in dept_data.items():
                if k == queryset.model._meta.object_name:
                    params.update({"{}__in".format(field): dept_user for field in v})
            return queryset.filter(**params)

        dataScope_list = list(set(dataScope_list))
        logger.debug(dataScope_list)
        dataScope_list.sort(reverse=True)
        # 有多个角色时，数据权限按照多个角色中最大的数据权限来返回
        # ("1", "全部数据权限"),
        # ("2", "自定数据权限"),
        # ("3", "本部门数据权限"),
        # ("4", "本部门及以下数据权限"),
        # ("5", "仅本人数据权限"),

        if min(dataScope_list) == "1":
            return queryset
        # 4. 只为仅本人数据权限时只返回过滤本人数据，并且部门为自己本部门(考虑到用户会变部门，只能看当前用户所在的部门数据)
        if "5" in dataScope_list:
            if len(domain_fields) == 0:
                return queryset.filter(creator=request.user, dept_belong_id=user_dept_id)
            else:
                user = Em_Basic.objects.filter(emp_id=user_empid)
                if user:
                    user_id = user.first().id
                else:
                    user_id = request.user.id
                _conditions = {}
                for dc, dfs in domain_fields.items():
                    if dc == queryset.model._meta.object_name:
                        for df in dfs:
                            _conditions[df] = user_id
                return queryset.filter(**_conditions)

        queryset = check_menu_permission(request=request, queryset=queryset)
        return queryset



class DataLevelPermissionsFilter(BaseFilterBackend):
    """
    数据 级权限过滤器
    0. 获取用户的部门id，没有部门则返回空
    1. 判断过滤的数据是否有创建人所在部门 "creator" 字段,没有则返回全部
    2. 如果用户没有关联角色则返回本部门数据
    3. 根据角色的最大权限进行数据过滤(会有多个角色，进行去重取最大权限)
    3.1 判断用户是否为超级管理员角色/如果有1(所有数据) 则返回所有数据

    4. 只为仅本人数据权限时只返回过滤本人数据，并且部门为自己本部门(考虑到用户会变部门，只能看当前用户所在的部门数据)
    5. 自定数据权限 获取部门，根据部门过滤

    **现行**
    """

    def filter_queryset(self, request, queryset, view):

        # 0.匿名用户不允许访问
        if isinstance(request.user, AnonymousUser):
            logger.debug("匿名用户")
            # return queryset.none()
            return queryset

        # 1. 获取用户的部门id，没有部门则返回空
        user_dept_id = getattr(request.user, "dept_id")
        if getattr(request.user, "user_type", None) != 2:
            if not user_dept_id:
                return queryset.none()

            # 1. 判断过滤的数据是否有创建人所在部门 "dept_belong_id" 字段
            # if not getattr(queryset.model, "dept_belong_id", None):
            #     return queryset

            # 2. 如果用户没有关联角色则返回本部门数据
            if not hasattr(request.user, "role"):
                return queryset.filter(dept_belong_id=user_dept_id)

            user_empid = getattr(request.user, "username")
            if not user_empid:
                return queryset.none()

        # 2. 根据所有角色 获取所有权限范围
        role_list = request.user.role.filter(status="1").values("admin", "dataScope", "domainFields", "modelKey")
        dataScope_list = []
        domain_fields = {}
        dept_data = {}
        dept_perm = False
        salary_perm = False

        for ele in role_list:
            # 3.1 判断用户是否为超级管理员角色/如果有1(所有数据) 则返回所有数据
            if "1" == ele.get("dataScope") or ele.get("admin") == True:
                return queryset
            if ele.get("dataScope") == "3" and ele.get("domainFields") and ele.get("modelKey"):
                model = ele["modelKey"]
                domain = ele["domainFields"].split(",")
                dept_data[model] = dept_data.get(model, []) + domain
                dept_perm = True
            dataScope_list.append(ele.get("dataScope"))
            if ele.get("domainFields") and ele.get("modelKey") and ele.get("dataScope") == "5":
                if ele.get("modelKey") != "BaseModel":
                    if ele.get("modelKey") in domain_fields:
                        domain_fields[ele.get("modelKey")] += ele.get("domainFields").split(",")
                    else:
                        domain_fields[ele.get("modelKey")] = ele.get("domainFields").split(",")
                elif ele.get("domainFields") == "emp_id":
                    salary_perm = True

        if dept_perm and user_dept_id and "UserProfile" == queryset.model._meta.object_name:
            return queryset.filter(dept=user_dept_id)

        if salary_perm and issubclass(queryset.model, BaseModel):
            return queryset.filter(emp_id=user_empid)

        if dept_data and user_empid:
            dept = list(Em_Basic.objects.filter(emp_id=user_empid).values_list("dept", flat=True))
            dept_user = list(Em_Basic.objects.filter(dept__in=dept).values_list("id", flat=True))
            params = {}
            for k, v in dept_data.items():
                if k == queryset.model._meta.object_name:
                    params.update({"{}__in".format(field): dept_user for field in v})
            return queryset.filter(**params)

        dataScope_list = list(set(dataScope_list))
        logger.debug(dataScope_list)
        dataScope_list.sort(reverse=True)
        # 有多个角色时，数据权限按照多个角色中最大的数据权限来返回
        # ("1", "全部数据权限"),
        # ("2", "自定数据权限"),
        # ("3", "本部门数据权限"),
        # ("4", "本部门及以下数据权限"),
        # ("5", "仅本人数据权限"),

        if min(dataScope_list) == "1":
            return queryset
        # 4. 只为仅本人数据权限时只返回过滤本人数据，并且部门为自己本部门(考虑到用户会变部门，只能看当前用户所在的部门数据)
        # if dataScope_list == ["5"]:
        #     return queryset.filter(creator=request.user, dept_belong_id=user_dept_id)
        # if dataScope_list == ["5"]:
        if "5" in dataScope_list:
            if len(domain_fields) == 0:
                return queryset.filter(creator=request.user, dept_belong_id=user_dept_id)
            else:
                user = Em_Basic.objects.filter(emp_id=user_empid)
                if user:
                    user_id = user.first().id
                else:
                    user_id = request.user.id
                _conditions = {}
                for dc, dfs in domain_fields.items():
                    if dc == queryset.model._meta.object_name:
                        for df in dfs:
                            _conditions[df] = user_id
                return queryset.filter(**_conditions)

        # 5. 自定数据权限 获取部门，根据部门过滤
        # if "5" not in dataScope_list:
        #     dept_list = []
        #     for ele in dataScope_list:
        #         if ele == "2":
        #             dept_list.extend(request.user.role.filter(status="1").values_list("dept__id", flat=True))
        #         elif ele == "3":
        #             dept_list.append(user_dept_id)
        #         elif ele == "4":
        #             dept_list.extend(
        #                 get_dept(
        #                     user_dept_id,
        #                 )
        #             )
        #     if hasattr(queryset.model, "dept_belong_id"):
        #         return queryset.filter(dept_belong_id__in=list(set(dept_list)))
        # return queryset.filter(dept_belong_id__in=list(set(dept_list)))

        queryset = check_menu_permission(request=request, queryset=queryset)
        return queryset